package com.test.elasticsearch.utils;

import com.alibaba.fastjson.JSON;

import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;

import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.CreateIndexRequest;
import org.elasticsearch.client.indices.CreateIndexResponse;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author JunHao Deng
 * @Title: 
 * @date 2021/03/25 11:08
 * @description： es常用方法工具类
 * 其实就是请求响应 request  response
 * Json.toJsonString(t) 将对象转化为Json字符串
 * timeout：限制请求时间
 **/
@Component
public class EsUtils<T> {
    @Autowired
    @Qualifier("restHighLevelClient")
    //一个接口有多个实现类，@Qualifier指明@Autowired具体注入哪个实现类
    private RestHighLevelClient client;

    /**
     * 判断索引（数据库）是否存在
     * @param index
     * @return
     * @throws IOException
     */
    public boolean existsIndex(String index) throws IOException {
        GetIndexRequest request = new GetIndexRequest(index);
        boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
        return exists;
    }

    /**
     * 创建索引
     * @param index
     * @return
     * @throws IOException
     */
    public boolean createIndex(String index) throws IOException {
        CreateIndexRequest request = new CreateIndexRequest(index);
        CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
        return createIndexResponse.isAcknowledged();
    }

    /**
     * 删除索引
     * @param index
     * @return
     * @throws IOException
     */
    public boolean deleteIndex(String index) throws IOException {
        DeleteIndexRequest request = new DeleteIndexRequest(index);
        AcknowledgedResponse response = client.indices().delete(request, RequestOptions.DEFAULT);
        return response.isAcknowledged();
    }

    /**
     * 判断某索引下的文档id（查找指定文件，id不必为数字，id是string类型）是否存在
     * @param index
     * @param id
     * @return
     * @throws IOException
     */
    public boolean docExists(String index , String id , T t) throws IOException {
        GetRequest getRequest = new GetRequest(index,id);
        getRequest.fetchSourceContext(new FetchSourceContext(false));
        //只是判断索引不需要获取_source
        getRequest.storedFields("_none_");
        boolean exists = client.exists(getRequest, RequestOptions.DEFAULT);
        return exists;
    }

    /***
     * 添加文档（行）（id）
     * @param index
     * @param id
     * @param t  添加的数据
     * @return
     * @throws IOException
     */
    public boolean addDoc(String index , String id , T t) throws IOException {
        IndexRequest indexRequest = new IndexRequest(index);
        indexRequest.id(id);

        indexRequest.timeout(TimeValue.timeValueDays(1));
        indexRequest.timeout("1s");
        //timeout
        indexRequest.source(JSON.toJSONString(t), XContentType.JSON);
        IndexResponse response = client.index(indexRequest, RequestOptions.DEFAULT);

        RestStatus status = response.status();
        return status==RestStatus.OK||status == RestStatus.CREATED;

    }

    /**
     * 根据id获取文档（行）
     * @param index
     * @param id
     * @return
     */
    public GetResponse getDoc(String index , String id) throws IOException {
        GetRequest getRequest = new GetRequest(index, id);
        GetResponse getResponse = client.get(getRequest, RequestOptions.DEFAULT);
        return getResponse;
    }

    /**
     * 批量导入doc，id可以手动也可以自动
     * 可以使用IndexRequest.id()
     * @param index
     * @param list
     * @return
     * @throws IOException
     */
    public boolean bulkAdd(String index , List<T> list)  throws IOException {
        BulkRequest bulkRequest = new BulkRequest();
        //timeout
        bulkRequest.timeout(TimeValue.timeValueMinutes(2));
        bulkRequest.timeout("2m");
        for (int i = 0; i < list.size(); i++){
            bulkRequest.add(new IndexRequest(index).source(JSON.toJSONString(list.get(i))));
        }
        BulkResponse bulkResponse = client.bulk(bulkRequest, RequestOptions.DEFAULT);

        return !bulkResponse.hasFailures();
    }

    /**
     * 更细指定文档
     * @param index
     * @param id
     * @param t
     * @return
     * @throws IOException
     */
    public boolean updateDoc(String index , String id , T t) throws IOException {
        UpdateRequest updateRequest = new UpdateRequest(index, id);
        updateRequest.doc(JSON.toJSONString(t));
        updateRequest.timeout(TimeValue.timeValueSeconds(1));
        updateRequest.timeout("1s");

        UpdateResponse updateResponse = client.update(updateRequest, RequestOptions.DEFAULT);
        return updateResponse.status()==RestStatus.OK;
    }

    /**
     * 删除id文档
     * @param index
     * @param id
     * @return
     * @throws IOException
     */
    public boolean delateDoc(String index,String id) throws IOException {
        DeleteRequest deleteRequest = new DeleteRequest(index, id);
        deleteRequest.timeout(TimeValue.timeValueSeconds(1));
        deleteRequest.timeout("1s");
        DeleteResponse deleteResponse = client.delete(deleteRequest, RequestOptions.DEFAULT);
        return deleteResponse.status()==RestStatus.OK;
    }

    /**
     * 查询
     * @param index
     * @param field
     * @param key
     * @throws IOException
     */
    public void search(String index, String field, String key , int from , int size) throws IOException {
        SearchRequest searchRequest = new SearchRequest(index);
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        //可以修改查询方法match/term ，和DSL语句一样 一层一层 ：{"query"{"match"{"field":"key"}}}
        searchSourceBuilder.query(QueryBuilders.matchQuery(field,key));
        //控制搜索
        //从第几条开始
        searchSourceBuilder.from(from);
        //打印多少条数据
        searchSourceBuilder.size(size);
        //最大请求时间
        searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
        searchRequest.source(searchSourceBuilder);
        SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        System.out.println(JSON.toJSONString(searchResponse.getHits()));
    }
}
